Skip to content

feat(af02): add deterministic surface scanner - #59

Closed
TheHalfMoon wants to merge 8 commits into
mainfrom
feat/af02-a0-surface-scanner
Closed

feat(af02): add deterministic surface scanner#59
TheHalfMoon wants to merge 8 commits into
mainfrom
feat/af02-a0-surface-scanner

Conversation

@TheHalfMoon

@TheHalfMoon TheHalfMoon commented Aug 28, 2026

Copy link
Copy Markdown
Owner

AF-02 Stack A0 — T012 scanner infrastructure

Canonical predecessor:

PR #58 merged as: d280e614f17732a9038662a4d193a3c5f2b5fa42
main tree after predecessor merge: c9051ec6a143ee477d471fe29225269db0da67d9
candidate head: dc4b9a38861e7ff9d3e0b34e07a8a2a43da473e5
base branch: main

This A0 infrastructure candidate implements T012 only. It does not alter surface-policy.json, does not commit source-universe/finding evidence, and does not claim T013.

T012 implementation

  • add exact syn = 3.0.3 with full and visit, matching the planning-frozen syn-af02-scanner identity;
  • add tools/af02-verifier/src/surface.rs as the planned SURFACE_SCANNER / SURFACE_POLICY_PARSER implementation path;
  • parse policy JSON with recursive duplicate-key rejection before typed projection;
  • enforce closed surface-policy structure and semantic references;
  • discover only Git-tracked Rust sources under the two closed roots;
  • parse every source with syn and scan cfg-disabled/dead syntax without scanning comments or literal contents;
  • resolve explicit/nested use aliases deterministically and emit uncertain findings for relevant glob ambiguity;
  • implement PATH_CALL, TYPE_CONSTRUCTOR, METHOD_CALL, and MACRO_TOKEN matching with exact identities;
  • prove constructor-bound method ownership only for a direct exact constructor or immutable same-block binding; mutable/unknown ownership remains uncertain;
  • assign deterministic per-file pre-order boundary-syntax ordinals and reject duplicate finding identities;
  • expose parse-surface-policy and scan-surface CLI entrypoints while leaving verify-pr fail-closed.

Temporal/lineage boundary

The canonical surface policy remains the earlier BOOTSTRAP policy. This candidate intentionally does not rebase that policy and does not carry dependent source-universe/finding evidence. dependent_evidence_allowed_in_same_candidate remains false. Policy rebase and T013 evidence remain separately governed after scanner authority is canonical.

Qualification

The previously qualified implementation head is retained exactly at dc4b9a38861e7ff9d3e0b34e07a8a2a43da473e5; after retargeting to canonical main, all path-applicable checks must be re-read against this exact candidate/base relation before merge. No PASS claim is made from stale base evidence.

@coderabbitai

coderabbitai Bot commented Aug 28, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@TheHalfMoon
TheHalfMoon changed the base branch from feat/af02-a0-authority-reconstruction to main August 29, 2026 05:05

Copy link
Copy Markdown
Owner Author

@coderabbitai review

Please review exact head 2fbbae7055aa963878148aaf742c2c5e5b446ed0 for AF-02 Stack A0 T012 after canonical predecessor PR #58 merged. Focus on deterministic syn=3.0.3 surface discovery semantics, alias/glob uncertainty handling, METHOD_CALL ownership classification, source-universe closure, duplicate finding identity rejection, and whether this candidate remains infrastructure-only without T013 dependent evidence.

Copy link
Copy Markdown
Owner Author

Superseding this draft PR without changing branch history because the connected GitHub GraphQL markPullRequestReadyForReview mutation is currently broken in the client. The replacement will use the same head branch feat/af02-a0-surface-scanner, exact head 2fbbae7055aa963878148aaf742c2c5e5b446ed0, and base main. No rebase, force-push, squash, or code mutation is involved. Qualification evidence for the replacement must be fresh in its own PR context.

@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== HEAD and requested commit =='
git rev-parse HEAD
git cat-file -t 2fbbae7055aa963878148aaf742c2c5e5b446ed0
git merge-base --is-ancestor c9051ec6a143ee477d471fe29225269db0da67d9 2fbbae7055aa963878148aaf742c2c5e5b446ed0 && echo 'canonical-base-is-ancestor=yes'

echo '== Changed paths: canonical base..candidate =='
git diff --name-status c9051ec6a143ee477d471fe29225269db0da67d9 2fbbae7055aa963878148aaf742c2c5e5b446ed0

echo '== Candidate commit summary =='
git show --no-patch --format=fuller 2fbbae7055aa963878148aaf742c2c5e5b446ed0

echo '== Relevant files =='
fd . tools/af02-verifier -t f 2>/dev/null | sort
fd 'Cargo\.toml|Cargo\.lock|surface-policy\.json' -t f . | sort

echo '== Scanner source outline =='
if [ -f tools/af02-verifier/src/surface.rs ]; then
  ast-grep outline tools/af02-verifier/src/surface.rs --items all --view expanded
fi

echo '== CLI/library source outlines =='
for f in tools/af02-verifier/src/*.rs; do
  [ -f "$f" ] || continue
  ast-grep outline "$f" --items all --view expanded
done

Length of output: 28075


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== Canonical predecessor ancestry =='
git merge-base --is-ancestor d280e614f17732a9038662a4d193a3c5f2b5fa42 2fbbae7055aa963878148aaf742c2c5e5b446ed0 && echo 'd280e61-is-ancestor=yes'
git merge-base d280e614f17732a9038662a4d193a3c5f2b5fa42 2fbbae7055aa963878148aaf742c2c5e5b446ed0

echo '== Dependency manifest and lockfile evidence =='
git diff d280e614f17732a9038662a4d193a3c5f2b5fa42..2fbbae7055aa963878148aaf742c2c5e5b446ed0 -- tools/af02-verifier/Cargo.toml tools/af02-verifier/Cargo.lock

echo '== Public CLI paths =='
sed -n '1,260p' tools/af02-verifier/src/main.rs

echo '== Scanner: policy parse, discovery, scan orchestration =='
sed -n '1,531p' tools/af02-verifier/src/surface.rs

echo '== Scanner: alias/glob and visitor ownership logic =='
sed -n '532,985p' tools/af02-verifier/src/surface.rs

echo '== Scanner: path validation and tests =='
sed -n '986,1280p' tools/af02-verifier/src/surface.rs

echo '== Added integration tests =='
sed -n '1,360p' crates/commandf-pkg/tests/af02_surface_scanner.rs

echo '== Policy lineage and evidence-related paths =='
python3 - <<'PY'
import json
p='specs/016-af-02-adversarial-test-strength/surface-policy.json'
with open(p, encoding='utf-8') as f:
    d=json.load(f)
print(json.dumps({
    'lineage': d.get('lineage'),
    'source_roots': d.get('source_roots'),
    'known_boundary_witnesses_count': len(d.get('known_boundary_witnesses', [])),
    'finding_exclusions_count': len(d.get('finding_exclusions', [])),
}, indent=2, sort_keys=True))
PY

echo '== All changed content names and evidence-keyword diff hits =='
git diff --unified=1 d280e614f17732a9038662a4d193a3c5e5b446ed0..2fbbae7055aa963878148aaf742c2c5e5b446ed0 \
  | rg -n -i -C2 'source.universe|finding|witness|evidence|surface.policy|t013|dependent'

Length of output: 62121


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== Exact scanner lines: import and ownership handling =='
nl -ba tools/af02-verifier/src/surface.rs | sed -n '532,925p'

echo '== Exact scanner lines: discovery and finding identities =='
nl -ba tools/af02-verifier/src/surface.rs | sed -n '159,275p'

echo '== Surface policy matcher shapes =='
python3 - <<'PY'
import json
p='specs/016-af-02-adversarial-test-strength/surface-policy.json'
with open(p, encoding='utf-8') as f:
    d=json.load(f)
for m in d['matchers']:
    print(json.dumps(m, sort_keys=True))
PY

echo '== Candidate changes relative to actual main merge parent =='
git diff --name-status HEAD^2 HEAD
git diff --unified=3 HEAD^2 HEAD -- \
  specs/016-af-02-adversarial-test-strength/surface-policy.json \
  specs/016-af-02-adversarial-test-strength \
  tools/af02-verifier \
  crates/commandf-pkg/tests/af02_surface_scanner.rs

echo '== Tracked Rust sources selected by the scanner predicate =='
git ls-files -z -- crates tools | python3 -c '
import sys
paths=[p.decode("utf-8") for p in sys.stdin.buffer.read().split(b"\0") if p]
selected=[]
for p in paths:
    parts=p.split("/")
    if (p.startswith("crates/") or p.startswith("tools/")) and p.endswith(".rs") and "src" in parts and parts.index("src")+1 < len(parts):
        selected.append(p)
print("\n".join(sorted(selected)))
'

echo '== Tests that cover local imports, glob-plus-qualified constructor bindings, and finding duplicates =='
rg -n -C2 -i 'local.*use|use .*::\*|glob|duplicate finding|identity|config_builder|method' \
  tools/af02-verifier/src/surface.rs crates/commandf-pkg/tests/af02_surface_scanner.rs

Length of output: 2031


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== Exact scanner lines: import and ownership handling =='
awk 'NR >= 532 && NR <= 925 { printf "%6d  %s\n", NR, $0 }' tools/af02-verifier/src/surface.rs

echo '== Exact scanner lines: discovery and finding identities =='
awk 'NR >= 159 && NR <= 275 { printf "%6d  %s\n", NR, $0 }' tools/af02-verifier/src/surface.rs

echo '== Surface policy matcher shapes =='
python3 - <<'PY'
import json
p='specs/016-af-02-adversarial-test-strength/surface-policy.json'
with open(p, encoding='utf-8') as f:
    d=json.load(f)
for m in d['matchers']:
    print(json.dumps(m, sort_keys=True))
PY

echo '== Candidate changes relative to actual main merge parent =='
git diff --name-status HEAD^2 HEAD
git diff --unified=3 HEAD^2 HEAD -- \
  specs/016-af-02-adversarial-test-strength/surface-policy.json \
  specs/016-af-02-adversarial-test-strength \
  tools/af02-verifier \
  crates/commandf-pkg/tests/af02_surface_scanner.rs

echo '== Tracked Rust sources selected by the scanner predicate =='
git ls-files -z -- crates tools | python3 -c '
import sys
paths=[p.decode("utf-8") for p in sys.stdin.buffer.read().split(b"\0") if p]
selected=[]
for p in paths:
    parts=p.split("/")
    if (p.startswith("crates/") or p.startswith("tools/")) and p.endswith(".rs") and "src" in parts and parts.index("src")+1 < len(parts):
        selected.append(p)
print("\n".join(sorted(selected)))
'

echo '== Relevant test coverage =='
rg -n -C2 -i 'local.*use|use .*::\*|glob|duplicate finding|identity|config_builder|method' \
  tools/af02-verifier/src/surface.rs crates/commandf-pkg/tests/af02_surface_scanner.rs || true

Length of output: 103417


@TheHalfMoon I reviewed exact head 2fbbae7055aa963878148aaf742c2c5e5b446ed0.

I found one issue.

  • P1 — Resolve block-scoped use aliases. collect_imports in tools/af02-verifier/src/surface.rs Line 537 only reads module-level Item::Use entries. Rust permits use inside a function or nested block. Therefore, this valid source produces no filesystem-read finding:

    fn f() {
        use std::fs as io;
        let _ = io::read("fixture");
    }

    The visitor scans the call with the module import table. That table has no io alias. Apply lexical import scopes during traversal, including scoped glob imports. Add tests for a block-scoped explicit alias, a block-scoped glob, and alias shadowing in nested blocks.

The review also confirmed these points from static inspection:

  • syn is pinned and locked at 3.0.3 with full and visit.
  • The scanner parses disabled syntax and does not inspect comments or string-literal text.
  • Source discovery uses Git-tracked paths, excludes non-regular files, limits discovery to the two closed source roots, and uses deterministic ordering.
  • Finding identity de-duplication uses (source_path, syntax_ordinal, matcher_id).
  • verify-pr remains fail-closed.
  • The candidate does not change surface-policy.json.
  • The policy still sets dependent_evidence_allowed_in_same_candidate to false.
  • The diff does not add T013 source-universe or finding evidence.

You are interacting with an AI system.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant